﻿using GrainManage.Entities;
using GrainManage.Server.Cache;
using System;
using System.Web.Mvc;

namespace GrainManage.Server.Controllers
{
    //[GrainManageAuthorization]
    //[GrainManagePerformance]
    public class BaseController : Controller
    {
        private System.Diagnostics.Stopwatch actionTimer;
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (IsTimeSpanNeeded)
            {
                actionTimer = System.Diagnostics.Stopwatch.StartNew();
            }
            base.OnActionExecuting(filterContext);
            BaseOutputModel result = new BaseOutputModel { Status = new StatusInfo() };
            try
            {
                int statusCode = ExecuteFilter(filterContext);
                if (statusCode > -1)
                {
                    string message = CachedStatusMessage.GetMessage(statusCode);
                    result.Status.StatusCode = statusCode;
                    result.Status.Message = message;
                    filterContext.Result = Json(result, JsonRequestBehavior.AllowGet);
                }
            }
            catch (Exception e)
            {
                result.Status.StatusCode = StatusCode.Failed;
                result.Status.Message = e.Message;
                filterContext.Result = Json(result, JsonRequestBehavior.AllowGet);
            }
        }

        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            if (IsTimeSpanNeeded)
            {
                actionTimer.Stop();
                var result = filterContext.Result as NewtonsoftJsonResult;
                if (result != null && result.Data != null)
                {
                    var data = result.Data as BaseOutputModel;
                    if (data != null && data.Status != null)
                    {
                        data.Status.TimeSpan = string.Format("{0} ms", actionTimer.ElapsedMilliseconds);
                    }
                }
            }
        }

        protected static NewtonsoftJsonResult NewtonsoftJson(object data)
        {
            return new NewtonsoftJsonResult { Data = data };
        }

        private static int ExecuteFilter(ActionExecutingContext filterContext)
        {
            int stateCode = -1;
            if (filterContext.HttpContext.Request.RequestType == "POST")
            {
                if (!filterContext.ActionParameters.ContainsKey("input"))
                {
                    stateCode = StatusCode.InvalidInput;
                }
                else if (filterContext.ActionDescriptor.ControllerDescriptor != null)
                {
                    var input = filterContext.ActionParameters["input"] as BaseInputModel;
                    if (input != null)
                    {
                        var authentication = input.Authentication;
                        if (authentication == null || string.IsNullOrEmpty(authentication.UserName))
                        {
                            stateCode = StatusCode.NameEmpty;
                        }
                        else
                        {
                            var service = ObjectFactory.AccountService;
                            var account = service.GetAccountView(authentication.UserName);
                            if (account == null)
                            {
                                stateCode = StatusCode.NameNotExist;
                            }
                            else
                            {
                                if (string.IsNullOrEmpty(authentication.Guid) || account.Guid != authentication.Guid)
                                {
                                    stateCode = StatusCode.IdentityFailed;
                                }
                                else if (!account.IsOnLine)
                                {
                                    stateCode = StatusCode.NotLogin;
                                }

                                if (account.CheckLoginIP)
                                {
                                    if (string.IsNullOrEmpty(authentication.LoginIP) || !GrainManage.Server.Util.IPUtil.IsIP(authentication.LoginIP))
                                    {
                                        authentication.LoginIP = GrainManage.Server.Util.IPUtil.RequestHostAddress;
                                    }
                                    if (account.LoginIP != authentication.LoginIP)
                                    {
                                        stateCode = StatusCode.IPChanged;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                if (!AppConfig.GetValue<bool>("AllowGet"))
                {
                    stateCode = StatusCode.GetNotAllowed;
                }
            }
            return stateCode;
        }

        private static bool IsTimeSpanNeeded
        {
            get
            {
                return AppConfig.GetValue<bool>("CalculateTimeSpan");
            }
        }
    }
}
